#include "c_cache.h"
#include <string.h>
#include <stdlib.h>

void TRingBufCreate(struct TRingBuf *self, void *buf, int buf_size) {
    self->buf = (char*)buf;
    self->write_pos_ = (char*)buf;
    self->read_pos_ = (char*)buf;
    self->end_pos_ = (char*)buf + buf_size;
    //self->data_size_ = 0;
    self->data_read_size_ = 0;
    self->data_write_size_ = 0;
}

void TRingBufClear(struct TRingBuf *self) {
    self->write_pos_ = self->buf;
    self->read_pos_ = self->buf;
//self->data_size_ = 0;
    self->data_read_size_ = 0;
    self->data_write_size_ = 0;
}


int TRingBufFreeSize(struct TRingBuf *self) {
    return (self->end_pos_ - self->buf) - (self->data_write_size_ - self->data_read_size_);
}


int TRingBufDataSize(struct TRingBuf *self) {
    return self->data_write_size_ - self->data_read_size_;
}


int TRingBufSize(struct TRingBuf *self) {
    return self->end_pos_ - self->buf;
}


void TRingBufWrite(struct TRingBuf *self, void *data, int data_size) {
    int free_size = TRingBufFreeSize(self);
    int result = data_size >= free_size ? free_size : data_size;
    int size = self->end_pos_ - self->write_pos_;
    if(size > result) 
    size = result;
    memmove(self->write_pos_, data, size);
    self->write_pos_ += size;
    if(self->write_pos_ >= self->end_pos_) {
        self->write_pos_ = self->buf;
        data_size = result - size;
        if(data_size > 0) {
        memmove(self->write_pos_, (char *)data + size, data_size);
        self->write_pos_ += data_size;
        }
    }
    self->data_write_size_ += result;
}


void TRingBufRead(struct TRingBuf *self, void *buf, int buf_size) {
    int data_size = TRingBufDataSize(self);
    int result = buf_size >= data_size ? data_size : buf_size;
    int size = self->end_pos_ - self->read_pos_;
    if(size > result) size = result;
    memmove(buf,(const void *)self->read_pos_, size); 
    self->read_pos_ += size;
    if(self->read_pos_ >= self->end_pos_){
        self->read_pos_ = self->buf;
        data_size = result - size;
        if(data_size > 0) {
        memmove((char *)buf + size, self->read_pos_, data_size);
        self->read_pos_ += data_size;
        }
    }
    self->data_read_size_ += result;
}
